﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CML.Grammer;
using CML.Data.Files;
using CML.Data.Instructions;

namespace Cml.UnitTests.Grammer
{
	[TestClass]
	public class CMLParserTests
	{
		[TestMethod]
		public void Test_good_1()
		{
			var result = RunGoodTest("CML.Samples.good.1.cml");
			Assert.AreEqual(8, result.Count);
			
		}

		[TestMethod]
		public void Test_Good_SingleEnvironment_OneName()
		{
			var result = RunGoodTest("CML.Samples.good.single-environment.1-name.cml");
			Assert.AreEqual(1, result.Count);
			Assert.AreEqual(1, result[0].environments.Count);
			Assert.AreEqual("uat", result[0].environments[0]);
		}

		[TestMethod]
		public void Test_Good_SingleEnvironment_TwoNames()
		{
			var result = RunGoodTest("CML.Samples.good.single-environment.2-names.cml");
			Assert.AreEqual(1, result.Count);
			Assert.AreEqual(2, result[0].environments.Count);
			Assert.AreEqual("sit", result[0].environments[0]);
			Assert.AreEqual("uat", result[0].environments[1]);
		}

		[TestMethod]
		public void Test_Good_SingleEnvironment_ThreeNames()
		{
			var result = RunGoodTest("CML.Samples.good.single-environment.3-names.cml");
			Assert.AreEqual(1, result.Count);
			Assert.AreEqual(3, result[0].environments.Count);
			Assert.AreEqual("sit", result[0].environments[0]);
			Assert.AreEqual("uat", result[0].environments[1]);
			Assert.AreEqual("prod", result[0].environments[2]);			
		}

		[TestMethod]
		public void Test_Good_Properties()
		{
			var result = RunGoodTest("CML.Samples.good.properties.cml");
			Assert.AreEqual(2, result.Count);
			Assert.AreEqual(1, result[0].files.Count);
			Assert.IsInstanceOfType(result[0].files[0], typeof(EditPropertyFile));
			var ef = (EditPropertyFile)result[0].files[0];
			Assert.AreEqual(3, ef.instructions.Count);
			Assert.IsInstanceOfType(ef.instructions[0], typeof(DeletePropertyInstruction));
			Assert.IsInstanceOfType(ef.instructions[1], typeof(AddPropertyInstruction));
			Assert.IsInstanceOfType(ef.instructions[2], typeof(UpdatePropertyInstruction));
				
			Assert.AreEqual(1, result[1].files.Count);
			Assert.IsInstanceOfType(result[1].files[0], typeof(AddPropertyFile));
			var af = (AddPropertyFile)result[1].files[0];
			Assert.AreEqual(3, af.instructions.Count);

			Assert.IsInstanceOfType(af.instructions[0], typeof(AddPropertyInstruction));
			Assert.IsInstanceOfType(af.instructions[1], typeof(AddPropertyInstruction));
			Assert.IsInstanceOfType(af.instructions[2], typeof(AddPropertyInstruction));
		}

		[TestMethod]
		public void Test_Bad_SingleEnvironment_MissingSecondName()
		{
			RunBadTest("CML.Samples.bad.single-environment.missing-second-name.cml");
		}

		[TestMethod]
		public void Test_Fail_NoEnvironments()
		{
			RunBadTest("CML.Samples.bad.missing-environment.cml");
		}

		[TestMethod]
		public void Test_Fail_InvalidEnvironmentsString()
		{
			RunBadTest("CML.Samples.bad.invalid-environment.cml");
		}

		public IList<CML.Data.Environments> RunGoodTest(string cmlResourceName)
		{
			try
			{
				var p = new Parser();
				var cml = CML.Resources.Resource.GetResource(cmlResourceName);
				var result = p.Parse(cml);
				return result;
			}
			catch (Exception x)
			{
				throw x;
			}
		}

		public void RunBadTest(string cmlResourceName)
		{
			try
			{
				var p = new Parser();
				string cml;
				try
				{
					cml = CML.Resources.Resource.GetResource(cmlResourceName);
				}
				catch
				{
					throw new ResourceNotFoundException();
				}
				var result = p.Parse(cml);
			}
			catch(ResourceNotFoundException x)
			{
				throw;
			}
			catch (Exception x)
			{
				return;
			}
			throw new Exception("Exception not thrown as expected.");
		}

		public class ResourceNotFoundException : Exception
		{
		}
	}
}
